package com.kenny.openimgur.util; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Build; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.transition.Transition; import android.transition.TransitionManager; import android.util.ArrayMap; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.kenny.openimgur.R; import com.kenny.openimgur.ui.GridItemDecoration; import com.kennyc.view.MultiStateView; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; /** * Created by kcampagna on 7/27/14. */ public class ViewUtils { /** * Returns the height of the actionbar * * @param context * @return */ public static int getActionBarHeight(Context context) { final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes( new int[]{android.support.v7.appcompat.R.attr.actionBarSize}); int abHeight = (int) styledAttributes.getDimension(0, 0); styledAttributes.recycle(); return abHeight; } /** * Sets the text for the Error View in a {@link MultiStateView} * * @param multiStateView The {@link MultiStateView} * @param textViewId TextView id in the ErrorView * @param errorMessage String resource of the error message */ public static void setErrorText(MultiStateView multiStateView, @IdRes int textViewId, @StringRes int errorMessage) { if (multiStateView == null) return; View errorView = multiStateView.getView(MultiStateView.VIEW_STATE_ERROR); if (errorView == null) { throw new NullPointerException("Error view is null"); } TextView errorTextView = (TextView) errorView.findViewById(textViewId); if (errorTextView != null) errorTextView.setText(errorMessage); } /** * Sets the text for the Error View in a {@link MultiStateView} * * @param multiStateView The {@link MultiStateView} * @param textViewId TextView id in the ErrorView * @param errorMessage String of the error message */ public static void setErrorText(MultiStateView multiStateView, @IdRes int textViewId, String errorMessage) { if (multiStateView == null) return; View errorView = multiStateView.getView(MultiStateView.VIEW_STATE_ERROR); if (errorView == null) { throw new NullPointerException("Error view is null"); } TextView errorTextView = (TextView) errorView.findViewById(textViewId); if (errorTextView != null) errorTextView.setText(errorMessage); } /** * Sets the text for the empty view in a {@link MultiStateView} * * @param multiStateView The {@link MultiStateView} * @param textViewId TextView id in the Empty View * @param emptyMessage The empty message */ public static void setEmptyText(MultiStateView multiStateView, @IdRes int textViewId, String emptyMessage) { if (multiStateView == null) return; View emptyView = multiStateView.getView(MultiStateView.VIEW_STATE_EMPTY); if (emptyView == null) { throw new NullPointerException("Empty view is null"); } TextView emptyTextView = (TextView) emptyView.findViewById(textViewId); if (emptyTextView != null) emptyTextView.setText(emptyMessage); } /** * Sets the text for the empty view in a {@link MultiStateView} * * @param multiStateView The {@link MultiStateView} * @param textViewId TextView id in the Empty View * @param emptyMessage The empty message */ public static void setEmptyText(MultiStateView multiStateView, @IdRes int textViewId, @StringRes int emptyMessage) { if (multiStateView == null) return; View emptyView = multiStateView.getView(MultiStateView.VIEW_STATE_EMPTY); if (emptyView == null) { throw new NullPointerException("Empty view is null"); } TextView emptyTextView = (TextView) emptyView.findViewById(textViewId); if (emptyTextView != null) emptyTextView.setText(emptyMessage); } /** * Sets up a {@link RecyclerView} for a Grid style * * @param context App context * @param recyclerView The {@link RecyclerView} to setup */ public static void setRecyclerViewGridDefaults(@NonNull Context context, @NonNull RecyclerView recyclerView) { Resources res = context.getResources(); int numColumns = res.getInteger(R.integer.gallery_num_columns); int gridSpacing = res.getDimensionPixelSize(R.dimen.grid_padding); setRecyclerViewGridDefaults(context, recyclerView, numColumns, gridSpacing); } /** * Sets up a {@link RecyclerView} for a Grid style * * @param context App context * @param recyclerView The {@link RecyclerView} to setup * @param numColumns Number of columns the {@link RecyclerView} grid has * @param gridSpacing The spacing between the grid items */ public static void setRecyclerViewGridDefaults(@NonNull Context context, @NonNull RecyclerView recyclerView, int numColumns, int gridSpacing) { recyclerView.setLayoutManager(new GridLayoutManager(context, numColumns)); recyclerView.addItemDecoration(new GridItemDecoration(gridSpacing, numColumns)); } /** * Attempts to clear the decor view from the transition manager which causes a leak. * <p/><a href="http://stackoverflow.com/questions/32698049/sharedelement-and-custom-entertransition-causes-memory-leak">StackOverflow * Explanation</a> * * @param activity */ public static void fixTransitionLeak(@NonNull Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; Class transitionManagerClass = TransitionManager.class; try { Field runningTransitionsField = transitionManagerClass.getDeclaredField("sRunningTransitions"); runningTransitionsField.setAccessible(true); //noinspection unchecked ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>> runningTransitions = (ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>) runningTransitionsField.get(transitionManagerClass); if (runningTransitions.get() == null || runningTransitions.get().get() == null) { return; } ArrayMap map = runningTransitions.get().get(); View decorView = activity.getWindow().getDecorView(); if (map.containsKey(decorView)) { map.remove(decorView); } } catch (NoSuchFieldException e) { // Nothing } catch (IllegalAccessException e) { // Nothing } } }